/*
 *  Filename:      gsl_debug.h
 *  Author:         Erick Huang<erickhuang1989@gmail.com>
 *  Revised:       2013-06-10
 *  Description:  
 *                      Some functions for debuging .
 *
 *  Copyright (c) Erick Huang. All rights reserved.
 */

#ifndef GSL_DEBUG_H
#define GSL_DEBUG_H

#ifdef __cplusplus
extern "C" {
#endif  /*__cplusplus*/

#include <stdlib.h>
#include <stdarg.h>
#include "gsl_defs.h"

#define GSL_DEBUG_MODE
//#define GSL_NOMESSAGE_MODE

typedef enum {
	GSL_LOGLEV_DEBUG      = 1,
	GSL_LOGLEV_MESSAGE    = 1 << 1,
	GSL_LOGLEV_WARNING    = 1 << 2,
	GSL_LOGLEV_ERROR      = 1 << 3,
	GSL_LOGLEV_FATAL      = 1 << 4,
	GSL_LOGLEV_END = 1 << 5
} GslLogLevel;

extern void gsl_set_log_file(FILE *file);
extern void gsl_set_log_level_mask(UINT32 levelmask);




extern void __gsl_logv_out(GslLogLevel lev, const char *fmt, va_list args);
extern UINT32 __gsl_log_mask;

#define gsl_log_level_enabled(level)	(__gsl_log_mask & (level))

#define gsl_logv(level,fmt,args)       \
{                                      \
	if (gsl_log_level_enabled(level))  \
		__gsl_logv_out(level,fmt,args);  \
	if ((level) == GSL_LOGLEV_FATAL)          \
		abort();                       \
}while(0)

#ifdef GSL_DEBUG_MODE
static inline void gsl_debug(const char *fmt,...)
{
  va_list args;
  va_start(args, fmt);
  gsl_logv(GSL_LOGLEV_DEBUG, fmt, args);
  va_end(args);
}
#else
static inline void gsl_debug(const char *fmt,...)
{
	/* NOP */
}
#endif

#ifdef GSL_NOMESSAGE_MODE
static inline void gsl_log(GslLogLevel lev, const char *fmt,...)
{
	/* NOP */
}

static inline void gsl_message(const char *fmt,...)
{
	/* NOP */
}

static inline void gsl_warning(const char *fmt,...)
{
	/* NOP */
}

#else

static inline void gsl_log(GslLogLevel lev, const char *fmt,...) {
	va_list args;
	va_start(args, fmt);
	gsl_logv(lev, fmt, args);
 	va_end(args);
}

static inline void gsl_message(const char *fmt,...)
{
	va_list args;
	va_start(args, fmt);
	gsl_logv(GSL_LOGLEV_MESSAGE, fmt, args);
	va_end(args);
}

static inline void gsl_warning(const char *fmt,...)
{
	va_list args;
	va_start(args, fmt);
	gsl_logv(GSL_LOGLEV_WARNING, fmt, args);
	va_end(args);
}
#endif


static inline void gsl_error(const char *fmt,...)
{
	va_list args;
	va_start(args, fmt);
	gsl_logv(GSL_LOGLEV_ERROR, fmt, args);
	va_end(args);
}

static inline void gsl_fatal(const char *fmt,...)
{
	va_list args;
	va_start(args, fmt);
	gsl_logv(GSL_LOGLEV_FATAL, fmt, args);
	va_end(args);
}



// helper macros
#define return_if_fail(expr)  do{  \
	if (!(expr))                   \
		{printf("%s:%i- assertion" #expr "failed\n",__FILE__,__LINE__); return;} \
	}while(0)
#define return_val_if_fail(expr,ret)   do{  \
	if (!(expr))                            \
		{printf("%s:%i- assertion" #expr "failed\n",__FILE__,__LINE__); return (ret);} \
	}while(0)




#ifdef __cplusplus
}
#endif  /*__cplusplus*/

#endif  /* GSL_DEBUG_H */